home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / modes / c-fill.el.z / c-fill.el
Encoding:
Text File  |  1998-05-21  |  8.7 KB  |  273 lines

  1. ;;; C comment mode - An auto-filled comment mode for gnu c-mode.
  2. ;;;
  3. ;;; Author:      Robert Mecklenburg
  4. ;;;        Computer Science Dept.
  5. ;;;              University of Utah
  6. ;;; From: mecklen@utah-gr.UUCP (Robert Mecklenburg)
  7. ;;;   Also hartzell@Boulder.Colorado.EDU
  8. ;;; (c) 1986, University of Utah
  9. ;;;
  10. ;;; Everyone is granted permission to copy, modify and redistribute
  11. ;;; this file, provided the people they give it to can.
  12.  
  13. ;;; Synched up with: Not in FSF.
  14.  
  15. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  16. ;;;
  17. ;;; I have written a "global comment" minor-mode which performs auto-fill,
  18. ;;; fill-paragraph, and auto-indentation functions.  This function only
  19. ;;; works for comments which occupy an entire line (not comments to the
  20. ;;; right of code).  The mode has several options set through variables.
  21. ;;; If the variable c-comment-starting-blank is non-nil multi-line
  22. ;;; comments come out like this:
  23. ;;; 
  24. ;;;     /*
  25. ;;;      * Your favorite 
  26. ;;;      * multi-line comment.
  27. ;;;      */
  28. ;;; 
  29. ;;; otherwise they look like this:
  30. ;;; 
  31. ;;;     /* Your Favorite
  32. ;;;      * multi-line comment.
  33. ;;;      */
  34. ;;; 
  35. ;;; If the variable c-comment-hanging-indent is non-nil K&R style comments
  36. ;;; are indented automatically like this:
  37. ;;; 
  38. ;;;     /* my_func - For multi-line comments with hanging indent
  39. ;;;      *         the text is lined up after the dash.
  40. ;;;      */
  41. ;;; 
  42. ;;; otherwise the text "the text" (!) is lined up under my_func.  If a
  43. ;;; comment fits (as typed) on a single line it remains a single line
  44. ;;; comment even if c-comment-starting-blank is set.  If
  45. ;;; c-comment-indenting is non-nil hitting carriage return resets the
  46. ;;; indentation for the next line to the current line's indentation
  47. ;;; (within the comment) like this:
  48. ;;; 
  49. ;;;     /* Typing along merrily....
  50. ;;;      *     Now I indent with spaces, when I hit return
  51. ;;;      *     the indentation is automatically set to 
  52. ;;;      *     ^ here.
  53. ;;;      */
  54. ;;; 
  55. ;;; Due to my lack of understanding of keymaps this permanently resets M-q
  56. ;;; to my own fill function.  I would like to have the comment mode
  57. ;;; bindings only in comment mode but I can't seem to get that to work.
  58. ;;; If some gnu guru can clue me in, I'd appreciate it.
  59. ;;;
  60. (defvar c-comment-starting-blank t
  61.   "*Controls whether global comments have an initial blank line.")
  62. (defvar c-comment-indenting t
  63.   "*If set global comments are indented to the level of the previous line.")
  64. (defvar c-comment-hanging-indent t
  65.   "*If true, comments will be automatically indented to the dash.")
  66. (defvar c-hang-already-done t
  67.   "If true we have performed the haning indent already for this comment.")
  68.  
  69.  
  70. ;;;
  71. ;;; c-comment-map - This is a sparse keymap for comment mode which
  72. ;;;             gets inserted when c-comment is called.
  73. ;;; 
  74. (defvar c-comment-mode-map ()
  75.   "Keymap used in C comment mode.")
  76. (if c-comment-mode-map
  77.     ()
  78.   (setq c-comment-mode-map (copy-keymap c-mode-map))
  79.   (define-key c-comment-mode-map "\e\r" 'newline)
  80.   (define-key c-comment-mode-map "\eq" 'set-fill-and-fill)
  81.   (define-key c-comment-mode-map "\r" 'set-fill-and-return))
  82.  
  83. ;;;
  84. ;;; c-comment - This is a filled comment mode which can format
  85. ;;;         indented text, do hanging indents, and symetric
  86. ;;;         placement of comment delimiters.
  87. ;;; 
  88. (defun c-comment ()
  89.   "Edit a C comment with filling and indentation.
  90. This performs hanging indentation, symmetric placement of delimiters,
  91.  and Indented-Text mode style indentation.  Type 'M-x apropos
  92. c-comment' for information on options."
  93.   (interactive)
  94.   (let
  95.       ;; Save old state.
  96.       ((auto-fill-function (if c-comment-indenting
  97.                    'do-indented-auto-fill 'do-auto-fill))
  98. ;       (comment-start nil)
  99.        (comment-multi-line t)
  100.        (comment-start-skip "/*\\*+[     ]*")
  101.        (paragraph-start-ref paragraph-start)
  102.        fill-prefix paragraph-start paragraph-separate opoint)
  103.  
  104.     ;; Determine if we are inside a comment.
  105.     (setq in-comment
  106.       (save-excursion
  107.         (and (re-search-backward "/\\*\\|\\*/" 0 t)
  108.          (string= "/*" (buffer-substring (point) (+ (point) 2))))))
  109.  
  110.     ;; Indent the comment and set the fill prefix to comment continuation
  111.     ;; string.  If we are already in a comment get the indentation on
  112.     ;; the current line.
  113.     (setq c-hang-already-done nil)
  114.  
  115.     ;; Set the beginning of the comment and insert the blank line if needed.
  116.     (use-local-map c-comment-mode-map)
  117.     (if (not in-comment)
  118.     (progn (c-indent-line)
  119.            (insert "/* ")
  120.            (setq fill-prefix (get-current-fill (point)))
  121.            (recursive-edit)
  122.  
  123.            ;; If the comment fits on one line, place the close
  124.            ;; comment at the end of the line.  Otherwise, newline.
  125.            (setq opoint (point))
  126.            (if (and (save-excursion (beginning-of-line)
  127.                     (search-forward "/*" opoint t))
  128.             (<= (+ (current-column) 3) 79))
  129.            (insert " */")
  130.          (insert "\n*/"))
  131.  
  132.            (c-indent-line))
  133.       (progn (setq fill-prefix (get-current-fill (point)))
  134.          (recursive-edit)
  135.          (search-forward "*/" (buffer-size) t)
  136.          (forward-line 1)))
  137.  
  138.     ;; If starting blank enabled, insert a newline, etc., but only if
  139.     ;; this comment requires multiple lines.
  140.     (if c-comment-starting-blank
  141.     (save-excursion
  142.       (setq opoint (point))
  143.       (forward-line -1)
  144.       (if (or (null (search-forward "/*" opoint t))
  145.           (null (search-forward "*/" opoint t)))
  146.           (progn
  147.         (search-backward "/*")
  148.         (re-search-forward comment-start-skip opoint t)
  149.         (setq fill-prefix (get-current-fill (point)))
  150.         (if (not (looking-at "\n"))
  151.             (insert ?\n fill-prefix))))))
  152. ;            (indent-new-comment-line))))))
  153.  
  154.     ;; Move cursor to indentation.
  155.     (c-indent-line)
  156.     (use-local-map c-mode-map)
  157.     )
  158.   )
  159.  
  160.  
  161. ;;;
  162. ;;; set-fill-and-fill - Get the current fill for this line and fill
  163. ;;;             the paragraph.
  164. ;;; 
  165. (defun set-fill-and-fill (arg)
  166.   "Get the fill-prefix and fill the current paragraph."
  167.  
  168.   (interactive "P")
  169.   (setq fill-prefix (get-current-fill (point)))
  170.   (fill-paragraph arg))
  171.  
  172. ;;;
  173. ;;; set-fill-and-return - Set the current fill prefix and
  174. ;;;               indent-new-comment-line.
  175. ;;; 
  176. (defun set-fill-and-return ()
  177.   "Set the current fill prefix and move to the next line."
  178.  
  179.   (interactive)
  180.   (if c-comment-indenting
  181.       (setq fill-prefix (get-current-fill (point))))
  182.   (insert ?\n fill-prefix))
  183.  
  184. ;;;
  185. ;;; do-indented-auto-fill - Perform the auto-fill function, but get
  186. ;;;                 the fill-prefix first.
  187. ;;; 
  188. (defun do-indented-auto-fill ()
  189.   "Perform auto-fill, but get fill-prefix first."
  190.  
  191.   (let ((opoint (point)))
  192.     (save-excursion
  193.       (move-to-column (1+ fill-column))
  194.       (skip-chars-backward "^ \t\n")
  195.       (if (bolp)
  196.       (re-search-forward "[ \t]" opoint t))
  197.       ;; If there is a space on the line before fill-point,
  198.       ;; and nonspaces precede it, break the line there.
  199.       (if (save-excursion
  200.         (skip-chars-backward " \t")
  201.         (not (bolp)))
  202.  
  203.       ;; If we are wrapping to a new line, figure out the indentation on
  204.       ;; the current line first.
  205.       (progn
  206.         (setq fill-prefix (get-current-fill opoint))
  207.         (insert ?\n fill-prefix)))))
  208. ;        (indent-new-comment-line)))))
  209.   )
  210.  
  211.  
  212. ;;;
  213. ;;; get-current-fill - Get the fill-prefix for the current line.  This
  214. ;;;                assumes that the valid fill prefix is between
  215. ;;;                (beginning-of-line) and (point).
  216. ;;; 
  217. (defun get-current-fill (pnt)
  218.   "Get the current fill prefix.
  219. A valid fill prefix must be between the beginning of the line and point."
  220.  
  221.   (let ((opoint pnt) fill last-char)
  222.     (save-excursion
  223.       (beginning-of-line)
  224.       (setq fill
  225.         (buffer-substring (point)
  226.                   (progn
  227.                 (re-search-forward comment-start-skip opoint t)
  228.                 (point))))
  229.  
  230.       ;; Be sure there is trailing white space.
  231.       (setq last-char (substring fill (1- (length fill)) (length fill)))
  232.       (if (and (not (string= " " last-char))
  233.            (not (string= "    " last-char)))
  234.       (setq fill (concat fill " ")))
  235.  
  236.       (setq fill (replace-letter fill "/" " "))
  237.  
  238.       ;; Get the hanging indentation if we haven't already.
  239.       (if (and c-comment-hanging-indent (not c-hang-already-done))
  240.       (let ((curr (point))
  241.         (opnt (progn (end-of-line) (point))))
  242.         (beginning-of-line)
  243.         (if (search-forward " - " opnt t)
  244.         (progn
  245.           (setq fill (concat fill (make-string (- (point) curr) 32)))
  246.           (setq c-hang-already-done t)))))
  247.  
  248.       ;; Set the paragraph delimiters.
  249.       (setq paragraph-start (concat paragraph-start-ref
  250.                     "\\|^"
  251.                     (regexp-quote
  252.                      (substring fill
  253.                         0 (1- (length fill))))
  254.                     "$"))
  255.       (setq paragraph-separate paragraph-start))
  256.     fill)
  257.   )
  258.   
  259.  
  260. ;;;
  261. ;;; replace-letter - Given a string, an old letter and a new letter,
  262. ;;;              perform the substitution.
  263. ;;; 
  264. (defun replace-letter (str old-letter new-letter)
  265.   (let (new-str c
  266.     (sp 0)
  267.     (size (length str)))
  268.     (while (< sp size)
  269.       (setq c (substring str sp (1+ sp)))
  270.       (setq new-str (concat new-str (if (string= c old-letter) new-letter c)))
  271.       (setq sp (1+ sp)))
  272.     new-str))
  273.